﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using HdcSimulation.Resource;
using Microsoft.Win32;
using Microsoft.WindowsAPICodePack.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace HdcSimulation.ViewModel
{
    public partial class MainWindowVM : ObservableObject
    {
        private string image_path = "C:\\Users\\lizhe\\Desktop\\image.bmp";
        private string image_dir = "D:\\Work\\HDC\\data\\HDCSimulation\\HdcSimulation\\Script\\resized_images";


        [ObservableProperty]
        private int imageIndex = 0;//当前发送的image序号
        [ObservableProperty]
        private int imageCount = 0;//当前发送的image总数

        private uint udpSendBytes = 0;//发送了多少bytes
        private uint udpSendImageNumber = 0;//发送了多少张图片

        [ObservableProperty]
        private uint frameRate = 0;//计算出来的发送帧率
        [ObservableProperty]
        private uint bandwidth = 0;//计算出来的发送带宽
        /// <summary>
        /// 程序的Title
        /// </summary>
        [ObservableProperty]
        private string? appName;
        /// <summary>
        /// 通讯协议，udp/tcp
        /// </summary>
        [ObservableProperty]
        private string? protocl;
        /// <summary>
        /// 目标地址
        /// </summary>
        [ObservableProperty]
        private string? ip;
        [ObservableProperty]
        private string? port;
        [ObservableProperty]
        private string? localPort;
        /// <summary>
        /// 当前是否正在发送
        /// </summary>
        [ObservableProperty]
        private bool isSending = false;
        /// <summary>
        /// 循环发送
        /// </summary>
        [ObservableProperty]
        private bool cycleSend = false;
        /// <summary>
        /// 当前选中的图片路径
        /// </summary>
        [ObservableProperty]
        private string? selectedDirectory = "";
        /// <summary>
        /// 定时发送定时器
        /// </summary>
        private HighPrecisionTimer timer;
        private HighPrecisionTimer calcTimer;

        private int sendCycleMs = 0;

        private int sendFrameNumber = 0;

        [ObservableProperty]
        private double sendCycleTime = 0;
        public MainWindowVM() 
        {
            AppName = ConfigurationManager.AppSettings["appName"].ToString();

            Protocl = ConfigurationManager.AppSettings["protocol"].ToString();
            Ip = ConfigurationManager.AppSettings["ip"].ToString();
            Port = ConfigurationManager.AppSettings["targetPort"].ToString();
            localPort = ConfigurationManager.AppSettings["localPort"].ToString();

            sendCycleMs = Convert.ToInt32(ConfigurationManager.AppSettings["sendCycle"].ToString());

            selectedDirectory = Path.Combine(Directory.GetCurrentDirectory() , "Script\\resized_images\\1_out");

            imageList = GetImageUriList(image_dir);
            if(imageList != null && imageList.Count>0)
                currectImage = imageList.FirstOrDefault();


            //每张图片在timer中进行发送，发送周期就是timer.Interval
            timer = new HighPrecisionTimer(TimeSpan.FromMilliseconds(sendCycleMs), Timer_Tick, null);

            calcTimer = new HighPrecisionTimer(TimeSpan.FromMilliseconds(1000), CalcTimer_Tick, null);
            calcTimer.StartRepeating();
        }

        private DateTime lastTime = DateTime.MinValue;


        private void CalcTimer_Tick(object state)
        {
            TimeSpan time = DateTime.Now - lastTime;
            Bandwidth = (uint)(udpSendBytes * 1000.0 / time.TotalMilliseconds);
            FrameRate = (uint)(udpSendImageNumber * 1000.0 / time.TotalMilliseconds);
            udpSendBytes = 0;
            udpSendImageNumber = 0;
            lastTime = DateTime.Now;
        }

        /// <summary>
        /// 打开路径选择对话框
        /// </summary>
        [RelayCommand]
        private void cmdOpenDirectoryDialog()
        {

            var ofd = new CommonOpenFileDialog();

            ofd.IsFolderPicker = true;
            ofd.RestoreDirectory = false;
            ofd.EnsurePathExists = true;
            ofd.Multiselect = false;

            if(ofd.ShowDialog() ==  CommonFileDialogResult.Ok)
            {
                SelectedDirectory = ofd.FileName;
            }

        }
        /// <summary>
        /// 开始发送
        /// </summary>
        [RelayCommand]
        private void cmdStartSend()
        {
            try
            {
                //通过选择的路径获取图片列表
                if (string.IsNullOrEmpty(SelectedDirectory) == true || Directory.Exists(SelectedDirectory) == false)
                {
                    HandyControl.Controls.MessageBox.Show("选择的路径有误!");
                    return;
                }


                var tempImageUriList = GetImageUriList(SelectedDirectory);

                List<Uri> nuseImgUri = new List<Uri>();
                foreach (var item in tempImageUriList)
                {
                    BitmapImage img = new BitmapImage(item);
                    if (img.PixelHeight != 80 || img.PixelWidth != 320)
                    {
                        nuseImgUri.Add(item);
                    }
                }
                foreach (var item in nuseImgUri)
                {
                    tempImageUriList.Remove(item);
                }

                if (tempImageUriList == null || tempImageUriList.Count == 0)
                {

                    HandyControl.Controls.MessageBox.Show("当前路径下没有合适的图片文件，要求320*80 8bits的灰度图像！");
                    return;
                }

                ImageList = tempImageUriList;
                ImageIndex = 0;
                ImageCount = ImageList.Count;
            }
            catch (Exception ex)
            {
                HandyControl.Controls.MessageBox.Show($"错误：\n{ex.Message}");
                return;
            }

            timer.StartRepeating();

            IsSending = true;
        }
        /// <summary>
        /// 停止发送
        /// </summary>
        [RelayCommand]
        private void cmdStopSend()
        {
            timer.Stop();
            IsSending = false;
        }

        /// <summary>
        /// 通过路径获取图片Uri列表
        /// </summary>
        /// <param name="directory"></param>
        /// <returns></returns>
        private List<Uri>? GetImageUriList(string directory)
        {
            if(Directory.Exists(directory) == false)
            {
                return new List<Uri>();
            }
            List<Uri> ? imageUriList = new List<Uri> ();
            try
            {
                var imagePathList = Directory.GetFiles(directory).ToList();
                var imagePathListOrderBySeq = new string[imagePathList.Count];

                for (int i = 0; i < imagePathList.Count; i++)
                {
                    string numStr = imagePathList[i].Substring(imagePathList[i].IndexOf("seq") + 3).Split('_')[0].Replace(".bmp", "");
                    int num = int.Parse(numStr);
                    imagePathListOrderBySeq[num - 1] = imagePathList[i];
                }

                foreach (var item in imagePathListOrderBySeq)
                {
                    imageUriList.Add(new Uri(item));
                }
                return imageUriList;
            }
            catch
            {
                return new List<Uri>();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="imageUri"></param>
        /// <param name="seq"></param>

        private void SendImageByUri(Uri imageUri, int seq)
        {
            using (UdpClient udp = new UdpClient(new IPEndPoint(IPAddress.Any, int.Parse(localPort))))
            {
                IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(Ip), int.Parse(Port));

                BitmapImage image = new BitmapImage(imageUri);
                byte[] imageGray = GetBitmapImageGrayValue(image);

                uint frameLength = 1000;
                uint frameDataLength = frameLength - 11; // 11字节头部
                uint frameNumber = (uint)Math.Ceiling((double)imageGray.Length / frameDataLength);

                byte[] udpFrame = new byte[frameLength];

                for (int i = 0; i < frameNumber; i++)
                {
                    uint pixelStart = (uint)(i * frameDataLength);
                    uint pixelNumber = (uint)(imageGray.Length - pixelStart >= frameDataLength
                        ? frameDataLength
                        : imageGray.Length - pixelStart);

                    byte[] frameHeader = new byte[11];

                    // 1. 序号(2字节，大端模式)
                    frameHeader[0] = (byte)((seq >> 8) & 0xFF); // 高8位
                    frameHeader[1] = (byte)(seq & 0xFF);        // 低8位

                    // 2. 起始地址(3字节，大端模式)
                    frameHeader[2] = (byte)((pixelStart >> 16) & 0xFF); // 最高字节
                    frameHeader[3] = (byte)((pixelStart >> 8) & 0xFF);  // 中间字节
                    frameHeader[4] = (byte)(pixelStart & 0xFF);         // 最低字节

                    // 3. 数据长度(1.5字节=12位，大端模式)和总帧数(1.5字节=12位，大端模式)
                    // 修复警告：使用无符号类型避免符号扩展问题
                    uint dataLengthHigh = (pixelNumber >> 4) & 0xFF;
                    uint dataLengthLow = (pixelNumber & 0x0F);
                    uint fragmentSumHigh = (frameNumber >> 8) & 0x0F;

                    frameHeader[5] = (byte)dataLengthHigh;                    // 数据长度高8位
                    frameHeader[6] = (byte)((dataLengthLow << 4) | fragmentSumHigh); // 数据长度低4位 + 总帧数高4位

                    // 总帧数低8位
                    frameHeader[7] = (byte)(frameNumber & 0xFF);

                    // 4. 保留字段(3字节)
                    frameHeader[8] = 0;
                    frameHeader[9] = 0;
                    frameHeader[10] = 0;

                    // 填充UDP帧
                    Array.Copy(frameHeader, 0, udpFrame, 0, 11);
                    Array.Copy(imageGray, (int)pixelStart, udpFrame, 11, (int)pixelNumber);

                    // 发送实际长度的数据包（不是固定1000字节）
                    int actualLength = 11 + (int)pixelNumber;
                    udp.Send(udpFrame, actualLength, endPoint);
                    udpSendBytes += (uint)actualLength;
                }
            }
        }


        private DateTime sendLastTime;
        private void Timer_Tick(object state)
        {
            
            SendImageByUri(ImageList.ElementAt(ImageIndex),ImageIndex%32);

            sendFrameNumber++;

            udpSendImageNumber += 1;

            if (ImageIndex < ImageCount - 1)
            {
                ImageIndex++;
            }
            else
            {
                ImageIndex = 0;
            }
            CurrectImage = ImageList.ElementAt(ImageIndex);
            if (CycleSend == false)
            {
                timer.Stop();
                IsSending = false;
            }

            SendCycleTime = (DateTime.Now - sendLastTime).TotalMilliseconds;
            sendLastTime = DateTime.Now;
        }
        /// <summary>
        /// bitmapImage转bitmap
        /// </summary>
        /// <param name="bitmapImage"></param>
        /// <returns></returns>
        public Bitmap BitmapImageToBitmap(BitmapImage bitmapImage)
        {
            // 使用内存流来保存像素数据
            using (var memoryStream = new MemoryStream())
            {
                // 将BitmapImage保存为bmp格式
                var encoder = new BmpBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bitmapImage));
                encoder.Save(memoryStream);

                // 从内存流创建Bitmap
                memoryStream.Position = 0;
                return new Bitmap(memoryStream);
            }
        }
        /// <summary>
        /// 获取bitmapimage中图像的灰度值
        /// </summary>
        /// <param name="bitmapImage"></param>
        /// <returns></returns>
        public byte[] GetBitmapImageGrayValue(BitmapImage bitmapImage)
        {
            using (var memoryStream = new MemoryStream())
            {
                // 将BitmapImage保存为bmp格式
                var encoder = new BmpBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bitmapImage));
                encoder.Save(memoryStream);

                // 从内存流创建Bitmap
                memoryStream.Position = 0;
                Bitmap bitMap = new Bitmap(memoryStream);
                byte[] grayPixel = new byte[bitMap.Width * bitMap.Height];

                var bitMapData = bitMap.LockBits(new Rectangle(0, 0, bitMap.Width, bitMap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bitMap.PixelFormat);

                try
                {
                    IntPtr pointer = bitMapData.Scan0;

                    Marshal.Copy(pointer, grayPixel, 0, grayPixel.Length);
                }
                finally
                {
                    bitMap.UnlockBits(bitMapData);
                }

                return grayPixel;
            }
        }
        /// <summary>
        /// 当前选中路径下的所有图片Uri列表
        /// </summary>
        [ObservableProperty]
        private List<Uri>? imageList;
        /// <summary>
        /// 当前正在执行发送的图像Uri
        /// </summary>
        [ObservableProperty]
        private Uri? currectImage;
    }
}
